package br.com.roteador.component;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.AsyncContext;
import javax.servlet.ServletContext;

import br.com.roteador.localizacao.Localizacao;
import br.com.roteador.motorista.Motorista;
import br.com.roteador.motorista.MotoristaDAO;

@Named("pushThread")
public class LocalizacaoPushThread implements Runnable {
	@Inject private MotoristaDAO motoristaDAO;
    @Inject private ServletContext sc;
    private Map<String, List<AsyncContext>> observadores = null;
    
    public LocalizacaoPushThread(){}
    
    @PostConstruct
    public void init(){
    	observadores = new HashMap<String, List<AsyncContext>>();
		List<Motorista> motoristas = motoristaDAO.recuperaMotoristas();
		for(Motorista motorista : motoristas){
			observadores.put(motorista.getImei(), null);
		}
    }
    
    @Override
    public void run() {
    	if (sc!=null){
    	    Queue<Localizacao> listaLocalizacao = new ConcurrentLinkedQueue<Localizacao>();
    	    sc.setAttribute("listaLocalizacao", listaLocalizacao);

    	      Executor bidExecutor = Executors.newCachedThreadPool(); 
    	      final Executor watcherExecutor = Executors.newCachedThreadPool();
    	      while(true) {
    	    	if(!listaLocalizacao.isEmpty()){
					 final Localizacao localizacao = listaLocalizacao.poll();
					 bidExecutor.execute(new Runnable(){
						 @SuppressWarnings("unchecked")
						public void run() {
							 observadores = (Map<String, List<AsyncContext>>)sc.getAttribute("observadores");
							 List<AsyncContext> watchers = observadores.get(localizacao.getImei()); 
							 for(final AsyncContext aCtx : watchers){
								 watcherExecutor.execute(new Runnable(){
									 public void run() {
										 try {
											 PrintWriter writer = aCtx.getResponse().getWriter();
											 writer.write("data: " + localizacao.getImei() + " \n\n");
										     writer.flush();
										 } catch (IOException e) {
											 e.printStackTrace();
										 }
									 };
								 });
							 }                           
						 }
					});
					 listaLocalizacao.remove(localizacao);
				 }
    	         try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
    	      }

    	}
    }
    
	public void setListaContexto() {
		sc.setAttribute("observadores", observadores);
	}
}